home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / Libraries / SpriteEngine / SpriteEngine.c < prev    next >
C/C++ Source or Header  |  1995-03-14  |  5KB  |  200 lines

  1. #include "SpriteTools.h"
  2.  
  3. /*
  4.  
  5. SpriteEngine
  6. ============
  7.  
  8. This demo sprite engine is designed for the following structure:
  9. (Lower units use the higher ones.)
  10.  
  11. SpriteTools.c: Utilities for loading and drawing
  12. |
  13. SpriteHanders.c: All custom code: Sprite init, movement, collisions
  14. |
  15. SpriteEngine.c: Main program, sprite engine
  16.  
  17. The only files you need to edit in order to change the sprite behavior are
  18. the files SpriteHandlers.c and SpriteHandlers.h.
  19.  
  20. */
  21.  
  22.  
  23. /* The actual sprite engine */
  24.  
  25.  
  26. static void InitSpriteEngine(Rect *offBounds, short backgroundPictureID)
  27. {
  28.     PicHandle    backgroundPicture;
  29.     GDHandle saveGD;
  30.     GWorldPtr savePort;
  31.     
  32.     MyNewGWorld(&gOffScreen, offBounds);
  33.     MyNewGWorld(&gBackScreen, offBounds);
  34.     
  35.     GetGWorld(&savePort, &saveGD);            /*Save the port/device*/
  36.     SetGWorld((GWorldPtr)gBackScreen, nil);
  37.     
  38.     EraseRect(offBounds);
  39.     
  40.     backgroundPicture = GetPicture(backgroundPictureID);
  41.     if (backgroundPicture != nil)
  42.     {
  43.         DrawPicture(backgroundPicture, offBounds);
  44.         ReleaseResource((Handle)backgroundPicture);
  45.     }
  46.     SetGWorld((GWorldPtr)gOffScreen, nil);
  47.     CopyBits(&gBackScreen->portBits, &gOffScreen->portBits, offBounds, offBounds, srcCopy, nil);
  48.     SetGWorld((GWorldPtr)myWindow, GetMainDevice());
  49.     CopyBits(&gOffScreen->portBits, &myWindow->portBits, offBounds, offBounds, srcCopy, nil);
  50.     SetGWorld(savePort, saveGD);
  51. } /*InitSpriteEngine*/
  52.  
  53.  
  54.  
  55. static void RunSpriteEngine()
  56. {
  57. #define  kWallBounce 7                            /*1/10-ths of speed kept after wallbounce*/
  58. #define  kBallDiameterSquared (32*32)            /*Diameter 32, squared*/
  59.  
  60.     Rect tmpRect;
  61.     GDHandle saveGD;
  62.     GWorldPtr savePort;
  63.     SpritePtr    theSprite, anotherSprite;
  64.     Rect    bounds1, bounds2;
  65.  
  66.     GetGWorld(&savePort, &saveGD);                /*Save the port/device*/
  67. /*1: Erase all sprites from gOffScreen*/
  68. /*Note: We keep the rectangles for erasing on the screen, later.*/
  69.     SetGWorld((GWorldPtr)gOffScreen, nil);
  70.  
  71.     theSprite = gSpriteList;
  72.     while (theSprite != nil)
  73.     {
  74.         theSprite->drawingRect = theSprite->face->portRect;
  75.         OffsetRect(&theSprite->drawingRect, theSprite->position.h, theSprite->position.v);
  76.         CopyBits(&gBackScreen->portBits, &gOffScreen->portBits, &theSprite->drawingRect, &theSprite->drawingRect, srcCopy, nil);
  77.         
  78.         theSprite = theSprite->next;
  79.     }
  80.  
  81. /*2: Change the position and speed*/
  82.     theSprite = gSpriteList;
  83.     while (theSprite != nil)
  84.     {
  85.         MoveSprite(theSprite);
  86.  
  87.         theSprite = theSprite->next;
  88.     }/*position/speed loop*/
  89.  
  90. /*3: Check for collisions*/
  91.     theSprite = gSpriteList;
  92.     while (theSprite != nil)    /*For all sprites in the list…*/
  93.     {
  94.         bounds1 = theSprite->face->portRect;
  95.         OffsetRect(&bounds1, theSprite->position.h, theSprite->position.v);
  96.  
  97.         anotherSprite = theSprite->next;
  98.         while (anotherSprite != nil)
  99.         {
  100.         /*compare its position to all following sprites*/
  101.             bounds2 = anotherSprite->face->portRect;
  102.             OffsetRect(&bounds2, anotherSprite->position.h, anotherSprite->position.v);
  103.  
  104.             if (SectRect(&bounds1, &bounds2, &tmpRect))
  105.                 HitSprite(theSprite, anotherSprite);
  106.  
  107.             anotherSprite = anotherSprite->next;
  108.         }
  109.         theSprite = theSprite->next;
  110.     } /*collision loop*/
  111.  
  112. /*4: Draw sprites in gOffScreen*/
  113. /*Note: PlotCIcon or DrawPicture are not very fast! We can speed it up my*/
  114. /*pre-drawing them in some offscreen, and CopyBits them from there.*/
  115.     theSprite = gSpriteList;
  116.     while (theSprite != nil)    /*For all sprites in the list…*/
  117.     {
  118.         tmpRect = theSprite->face->portRect;
  119.         OffsetRect(&tmpRect, theSprite->position.h, theSprite->position.v);
  120.         PlotFace(theSprite->face, gOffScreen, *(Point *)&tmpRect);
  121.  
  122.         theSprite = theSprite->next;
  123.     }
  124.  
  125. /*5: Copy sprites to the screen (gWind) - both old and new position!*/
  126. /*Note: Depending on what limitations we have on movement, we may be able to avoid the multiple*/
  127. /*CopyBitsing here. E.g. if sprites always move a maximum of 2 pixels, we can copy a 2 pixels*/
  128. /*larger area, etc.*/
  129.     SetGWorld((GWorldPtr)myWindow, saveGD); /*Vilken GD???*/
  130.     theSprite = gSpriteList;
  131.     while (theSprite != nil)    /*For all sprites in the list…*/
  132.     {
  133.         CopyBits(&gOffScreen->portBits, &myWindow->portBits, &theSprite->drawingRect, &theSprite->drawingRect, srcCopy, nil);
  134.         theSprite->drawingRect = theSprite->face->portRect;
  135.         OffsetRect(&theSprite->drawingRect, theSprite->position.h, theSprite->position.v);
  136.         CopyBits(&gOffScreen->portBits, &myWindow->portBits, &theSprite->drawingRect, &theSprite->drawingRect, srcCopy, nil);
  137.  
  138.         theSprite = theSprite->next;
  139.     }
  140.     SetGWorld(savePort, saveGD);
  141. }; /*RunSpriteEngine*/
  142.  
  143.  
  144.  
  145. /* Standard inits */
  146.  
  147. static void InitToolbox(void) {
  148.     InitGraf (&qd.thePort);
  149.     InitFonts ();
  150.     FlushEvents (everyEvent,0);
  151.     InitWindows ();
  152.     InitMenus ();
  153.     TEInit ();
  154.     InitDialogs (nil);
  155.     InitCursor ();
  156. } /*InitToolbox*/
  157.  
  158.  
  159. /* Initialize - create window, load graphics */
  160.  
  161. static void InitStuff()
  162. {
  163.     Rect    windowRectangle;
  164.  
  165. /*Set up the window*/
  166.     SetRect(&windowRectangle, 50, 50, 450, 350);
  167.     myWindow = NewCWindow(nil, &windowRectangle, "\pSprite test", true, documentProc, (WindowPtr)-1L, false, 0);
  168.     SetPort(myWindow);
  169.  
  170.     qd.randSeed = TickCount ();    /*Seed the random number generator*/
  171. } /*InitStuff*/
  172.  
  173.  
  174. #define    kBackgroundPictureID    128
  175.  
  176.  
  177. /* Main program */
  178.  
  179. void main(void)
  180. {
  181.     long    startTime;
  182.     
  183.     InitToolbox();
  184.     InitStuff();
  185.     InitSpriteEngine(&myWindow->portRect, kBackgroundPictureID);
  186.     InitSprites();
  187.     
  188.     HideCursor();
  189.     while (!Button())
  190.     {
  191.         startTime = TickCount();
  192.         RunSpriteEngine();
  193.         while (TickCount() < startTime + kFrameTime);
  194.     }
  195.     ShowCursor();
  196.     
  197.     FlushEvents(mDownMask, 0);
  198. } /*main*/
  199.  
  200.